package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.BooleanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.LearningRecordFormDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.tianji.learning.service.ILearningRecordService;
import com.tianji.learning.utils.RecordCacheUtil;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-12-08
 */
@Service
@AllArgsConstructor
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {


    private final ILearningLessonService lessonService;
    private final CourseClient courseClient;


    /**
     * 查询当前用户指定课程的学习进度
     * @param courseId
     * @return
     */
    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
        //查询当前用户的课程
        LearningLessonDTO lessonDTO = new LearningLessonDTO();
        LearningLesson lesson = lessonService.lambdaQuery()
                .eq(LearningLesson::getUserId, UserContext.getUser())
                .eq(LearningLesson::getCourseId, courseId)
                .ne(LearningLesson::getStatus, LessonStatus.EXPIRED)
                .one();
        if (lesson == null){
            return null;
        }
        //如果有该课程，根据课程id查询出课程记录
        lessonDTO.setId(lesson.getId());
        lessonDTO.setLatestSectionId(lesson.getLatestSectionId());
        List<LearningRecord> records = lambdaQuery().eq(LearningRecord::getUserId, UserContext
                        .getUser())
                .eq(LearningRecord::getLessonId, courseId)
                .list();
        List<LearningRecordDTO> recordDTOS = BeanUtils.copyList(records, LearningRecordDTO.class);
        lessonDTO.setRecords(recordDTOS);
        return lessonDTO;
    }

    @Autowired
    private CourseClient courseCliente;


    /**
     * 提交学习记录
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitLearingRecord(LearningRecordFormDTO dto) {

        Boolean isFirst ;
        //判断是否为视频
        if(dto.getSectionType() == SectionType.EXAM){
            //处理考试
            isFirst = handleExam(dto);
        }else {
            //处理视频
            isFirst = handleVideo(dto);
        }
        //如果不是第一次完成，就直接使用mq异步处理
        if (!isFirst){
            return;
        }
        //处理课程
        handleLesson(dto);
    }



    /**
     * 处理课表
     * @param dto
     */
    private void handleLesson(LearningRecordFormDTO dto) {
        //判断课程是否存在
        LearningLesson lesson = lessonService.getById(dto.getLessonId());
        if (lesson == null){
            throw new BizIllegalException("课程不存在");
        }
        Boolean allFinished = false;
        //为true就是完成操作
        //完成就更新课表,小节就加1
        //判断是否全部小节学习完成
        CourseFullInfoDTO course = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
        if (course == null) {
            throw new BizIllegalException("课程不存在，有问题");
        }
        if (course.getSectionNum() <= lesson.getLearnedSections() + 1) {
            //全部学习完成，就更新课表的状态为已完成
            allFinished = true;
        }
        //不管是否为已完成操作，都应该更新的字段
        lessonService.lambdaUpdate()
                .set(lesson.getStatus() == LessonStatus.NOT_BEGIN.getValue(), LearningLesson::getStatus, LessonStatus.LEARNING.getValue())
                .set(allFinished, LearningLesson::getStatus, LessonStatus.FINISHED)
                .setSql("learned_sections = learned_sections + 1")
                .eq(LearningLesson::getId, lesson.getId())
                .set(LearningLesson::getLatestLearnTime, dto.getCommitTime())
                .set(LearningLesson::getLatestSectionId, dto.getSectionId())
                .update();
    }

    @Autowired
    private RecordCacheUtil recordCacheUtil;

    /**
     * 处理视频
     * @param dto
     */
    private Boolean handleVideo(LearningRecordFormDTO dto) {
        //        //判断是否是第一次
        //这里从redis中查询
        LearningRecord old = readForCache(dto);

        if (old == null){
            //如果是空就是新增操作,就是之前没看过
            LearningRecord record = BeanUtils.copyBean(dto, LearningRecord.class);
            record.setUserId(UserContext.getUser());
            record.setFinished(false);
            record.setUpdateTime(dto.getCommitTime());
            save(record);
            return false;
        }
        //看过之前有记录，就是更新操作
        //获得进度是否超过50%
        boolean isFirst = (dto.getMoment() * 2) >= dto.getDuration() && BooleanUtils.isFalse(old.getFinished());
        if (isFirst){
            //如果是第一次完成，就直接清理缓存
            recordCacheUtil.clearnCache(dto.getLessonId(), dto.getSectionId());
            //一个视频的第一次请求，必须加入到数据库中
            boolean update = lambdaUpdate()
                    .set(isFirst, LearningRecord::getFinished, true)
                    .set(isFirst, LearningRecord::getFinishTime, dto.getCommitTime())
                    .eq(LearningRecord::getId, old.getId())
                    .update();
        }else {
            //没有完成，就加入缓存即可
            old.setMoment(dto.getMoment());
            recordCacheUtil.writeCache(old);
        }
        return isFirst;
    }

    //先从缓存中查询，如果没有查到，再从数据库中查询
    private LearningRecord readForCache(LearningRecordFormDTO dto) {
        LearningRecord old = recordCacheUtil.readCache(dto.getLessonId(), dto.getSectionId());
        if (old == null){
            //缓存中查不到，再从数据库中查询
             old = this.lambdaQuery()
                    .eq(LearningRecord::getLessonId, dto.getLessonId())
                    .eq(LearningRecord::getSectionId, dto.getSectionId())
                    .one();
             //如果数据库中也没有，就是真的没有
            if (old == null){
                return null;
            }
            //数据库中有，就放进缓存中
            recordCacheUtil.writeCache(old);
        }
        //缓存中有，就直接返回
        return old;

    }

    /**
     * 处理考试
     * @param dto
     */
    private Boolean handleExam(LearningRecordFormDTO dto) {
        //处理考试,直接提交就行
        LearningRecord record = BeanUtils.copyBean(dto, LearningRecord.class);
        record.setUserId(UserContext.getUser());
        record.setFinished(true);
        record.setUpdateTime(dto.getCommitTime());
        save(record);
        return true;
    }


}
